home *** CD-ROM | disk | FTP | other *** search
/ Software Vault: The Gold Collection / Software Vault - The Gold Collection (American Databankers) (1993).ISO / cdr25 / memsz130.zip / MEMSIZE.C < prev    next >
C/C++ Source or Header  |  1993-03-14  |  84KB  |  2,564 lines

  1. /************************************************************** MEMSIZE.C
  2.  *                                                                      *
  3.  * System Resources Monitor                        *
  4.  *                                                                      *
  5.  * Revision 1.30 (07/06/92)                        *
  6.  *                                                                      *
  7.  * (C) Copyright 1991-1992 by Richard W. Papo.                *
  8.  *                                    *
  9.  * This is 'FreeWare'.    As such, it may be copied and distributed    *
  10.  * freely.  If you want to use part of it in your own program, please    *
  11.  * give credit where credit is due.  If you want to change the        *
  12.  * program, please refer the change request to me or send me the    *
  13.  * modified source code.  I can be reached at CompuServe 72607,3111 or    *
  14.  * through the Magnum BBS for OS/2 (ID 2370).                *
  15.  *                                                                      *
  16.  ************************************************************************/
  17.  
  18. #define INCL_DOS
  19. #define INCL_WIN
  20. #define INCL_GPI
  21. #include <os2.h>
  22.  
  23. #include <direct.h>
  24. #include <process.h>
  25. #include <stdarg.h>
  26. #include <stddef.h>
  27. #include <stdio.h>
  28. #include <stdlib.h>
  29. #include <string.h>
  30.  
  31. #include <sys\types.h>
  32. #include <sys\stat.h>
  33.  
  34. #include "object.h"
  35. #include "about.h"
  36.  
  37. #include "memsize.h"
  38.  
  39. #define TRUE  1
  40. #define FALSE 0
  41.  
  42. #define NOT !
  43. #define OR  ||
  44. #define AND &&
  45.  
  46. #define PROGRAM_NAME "MEMSIZE"
  47.  
  48. #define ITEM_MEMORYFREE     0
  49. #define ITEM_SWAPFILESIZE   1
  50. #define ITEM_SWAPDISKFREE   2
  51. #define ITEM_SPOOLFILESIZE  3
  52. #define ITEM_CPULOAD        4
  53.  
  54.  
  55. /************************************************************************
  56.  *                          Type Definitions                            *
  57.  ************************************************************************/
  58.  
  59. typedef struct          // Data structure for item to be monitored.
  60. {
  61.   PCHAR  Name ;            // Text for item's profile name.
  62.   BOOL     Flag ;            // Flag: Show this item at this time?
  63.   PCHAR  Label ;           // Text to display on left part of line.
  64.   ULONG  Value ;           // Value to display on right part of line.
  65.   PCHAR  MenuOption ;           // Text to display in system menu.
  66.   USHORT MenuId ;           // ID for use in system menu.
  67.   ULONG  (*NewValue)           // Function to determine new value.
  68.     (void*,USHORT) ;
  69.   USHORT Parm ;            // Parameter to pass to NewValue function.
  70.   USHORT Divisor ;           // Amount to divide value by before display.
  71.   CHAR     Suffix ;           // Character to place after value.
  72. }
  73. ITEM ;
  74.  
  75. typedef struct        // Data structure for Timing Thread.
  76. {
  77.   TID tid ;
  78.   HWND hwndClient ;
  79.   ULONG *Count ;
  80. }
  81. TIMING_PARMS ;
  82.  
  83. typedef struct        // Data structure for Counting Thread.
  84. {
  85.   TID tid ;
  86.   ULONG *Count ;
  87. }
  88. COUNTING_PARMS ;
  89.  
  90. typedef struct        // Data structure for Calibration Thread.
  91. {
  92.   ULONG Count ;
  93. }
  94. CALIBRATION_PARMS ;
  95.  
  96. typedef struct          // Parameters saved to system.
  97. {
  98.   ITEM    *Items ;        // Items to display.
  99.   int     ItemCount ;
  100.  
  101.   SWP     Position ;        // Window size & location.
  102.   BOOL     fPosition ;
  103.  
  104.   BOOL     HideControls ;     // User options.
  105.  
  106.   CHAR     FontNameSize [80] ;    // Presentation Parameters
  107.   BOOL     fFontNameSize ;
  108.  
  109.   COLOR  BackColor ;
  110.   BOOL     fBackColor ;
  111.  
  112.   COLOR  TextColor ;
  113.   BOOL     fTextColor ;
  114. }
  115. PROFILE ;
  116.  
  117. typedef struct        // Data structure for window.
  118. {
  119.   ULONG          MaxCount ;
  120.   ULONG          Counter ;
  121.   ULONG      NewLoad ;
  122.  
  123.   PROFILE     Profile ;
  124.  
  125.   HWND           hwndTitleBar ;
  126.   HWND           hwndSysMenu ;
  127.   HWND           hwndMinMax ;
  128.  
  129.   char           SwapPath [_MAX_PATH] ;
  130.   int         MinFree ;
  131.  
  132.   char        *SpoolPath ;
  133.  
  134.   FONTMETRICS     FontMetrics ;
  135.  
  136.   TID            TimingThread ;
  137.   TIMING_PARMS   TimingParms ;
  138.  
  139.   TID            CountingThread ;
  140.   COUNTING_PARMS CountingParms ;
  141. }
  142. DATA ;
  143.  
  144.  
  145. /************************************************************************
  146.  *                         Function Prototypes                          *
  147.  ************************************************************************/
  148.  
  149. VOID main ( VOID ) ;
  150.  
  151. static METHODFUNCTION Create ;
  152. static METHODFUNCTION Destroy ;
  153. static METHODFUNCTION Size ;
  154. static METHODFUNCTION SaveApplication ;
  155. static METHODFUNCTION Timer ;
  156. static METHODFUNCTION Paint ;
  157. static METHODFUNCTION Command ;
  158. static METHODFUNCTION ButtonDown ;
  159. static METHODFUNCTION ButtonDblClick ;
  160. static METHODFUNCTION PresParamChanged ;
  161. static METHODFUNCTION Semaphore1 ;
  162.  
  163. static METHODFUNCTION QueryKeysHelp ;
  164. static METHODFUNCTION HelpError ;
  165. static METHODFUNCTION ExtHelpUndefined ;
  166. static METHODFUNCTION HelpSubitemNotFound ;
  167.  
  168. static void GetProfile ( PROFILE *Profile ) ;
  169. static void PutProfile ( PROFILE *Profile ) ;
  170.  
  171. static char *ScanSystemConfig ( char *Keyword ) ;
  172.  
  173. static void ResizeWindow ( HWND hwnd, PROFILE *Profile ) ;
  174.  
  175. static void HideControls
  176. (
  177.   BOOL fHide,
  178.   HWND hwndFrame,
  179.   HWND hwndSysMenu,
  180.   HWND hwndTitleBar,
  181.   HWND hwndMinMax
  182. ) ;
  183.  
  184. static void Debug ( HWND hwnd, char *Message, ... ) ;
  185.  
  186. static ULONG CalibrateLoad ( void ) ;
  187. static void _cdecl _far TimingThread ( TIMING_PARMS *Parms ) ;
  188. static void _cdecl _far CountingThread ( COUNTING_PARMS *Parms ) ;
  189. static void _cdecl _far CalibrationThread ( CALIBRATION_PARMS *Parms ) ;
  190.  
  191. static void UpdateWindow ( HWND hwnd, DATA *Data, BOOL All ) ;
  192.  
  193. static ULONG ComputeFreeMemory ( DATA *Data, USHORT Dummy ) ;
  194. static ULONG ComputeSwapSize   ( DATA *Data, USHORT Dummy ) ;
  195. static ULONG ComputeSwapFree   ( DATA *Data, USHORT Dummy ) ;
  196. static ULONG ComputeSpoolSize  ( DATA *Data, USHORT Dummy ) ;
  197. static ULONG ComputeCpuLoad    ( DATA *Data, USHORT Dummy ) ;
  198. static ULONG ComputeDriveFree  ( DATA *Data, USHORT Drive ) ;
  199.  
  200.  
  201. /************************************************************************
  202.  *                         Global Definitions                           *
  203.  ************************************************************************/
  204.  
  205. #define ID_MAIN  1
  206. #define ID_TIMER 1
  207.  
  208. static HAB hAB ;
  209. static HWND hwndHelp ;
  210.  
  211. static METHOD Methods [] =
  212. {
  213.   { WM_CREATE,                Create              },
  214.   { WM_DESTROY,               Destroy             },
  215.   { WM_SIZE,                  Size                },
  216.   { WM_MOVE,                  Size                },
  217.   { WM_SAVEAPPLICATION,       SaveApplication     },
  218.   { WM_TIMER,                 Timer               },
  219.   { WM_PAINT,                 Paint               },
  220.   { WM_COMMAND,               Command             },
  221.   { WM_BUTTON1DOWN,           ButtonDown          },
  222.   { WM_BUTTON2DOWN,           ButtonDown          },
  223.   { WM_BUTTON1DBLCLK,         ButtonDblClick      },
  224.   { WM_BUTTON2DBLCLK,         ButtonDblClick      },
  225.   { WM_PRESPARAMCHANGED,      PresParamChanged    },
  226.   { WM_SEM1,                  Semaphore1          },
  227.  
  228.   { HM_QUERY_KEYS_HELP,       QueryKeysHelp       },
  229.   { HM_ERROR,                 HelpError           },
  230.   { HM_EXT_HELP_UNDEFINED,    ExtHelpUndefined    },
  231.   { HM_HELPSUBITEM_NOT_FOUND, HelpSubitemNotFound }
  232. } ;
  233.  
  234. static CLASS Class =
  235. {
  236.   Methods,
  237.   sizeof(Methods)/sizeof(METHOD),
  238.   WinDefWindowProc,
  239.   sizeof(DATA),
  240.   0,
  241.   TRUE,
  242.   {
  243.     0,
  244.     FCF_TITLEBAR | FCF_SYSMENU | FCF_BORDER |
  245.       FCF_ICON | FCF_MINBUTTON | FCF_NOBYTEALIGN | FCF_ACCELTABLE,
  246.     0,
  247.     ID_MAIN
  248.   }
  249. } ;
  250.  
  251. HELPINIT HelpInit =
  252. {
  253.   sizeof ( HELPINIT ),
  254.   0L,
  255.   NULL,
  256.   MAKEP ( 0xFFFF, ID_MAIN ),
  257.   0,
  258.   0,
  259.   0,
  260.   0,
  261.   "\"System Resources\" Help Facility",
  262.   CMIC_HIDE_PANEL_ID,
  263.   "MEMSIZE.HLP"
  264. } ;
  265.  
  266.  
  267. /************************************************************************
  268.  *                                                                      *
  269.  *      Program Mainline                                                *
  270.  *                                                                      *
  271.  ************************************************************************/
  272.  
  273. VOID main ( VOID )
  274. {
  275.  /***********************************************************************
  276.   * Go execute the window object.                    *
  277.   ***********************************************************************/
  278.  
  279.   Object ( &hAB, NULL, CS_MOVENOTIFY, &HelpInit, &hwndHelp,
  280.     HWND_DESKTOP, ID_MAIN, &Class, "System Resources" ) ;
  281. }
  282.  
  283. /************************************************************************
  284.  *                                                                      *
  285.  *      Initialize main window.                                         *
  286.  *                                                                      *
  287.  ************************************************************************/
  288.  
  289. static MRESULT APIENTRY Create
  290. (
  291.   HWND hwnd,
  292.   USHORT msg,
  293.   MPARAM mp1,
  294.   MPARAM mp2,
  295.   void *data
  296. )
  297. {
  298.  /***********************************************************************
  299.   *                             Declarations                            *
  300.   ***********************************************************************/
  301.  
  302.   static PCHAR szMenuText [] =
  303.   {
  304.     "Save Defaults\tF2",
  305.     "Reset Defaults",
  306.     "Hide Controls",
  307.   } ;
  308.  
  309.   static MENUITEM MenuItems [] =
  310.   {
  311.     { MIT_END, MIS_TEXT,      0, IDM_SAVE_APPLICATION, NULL, 0 },
  312.     { MIT_END, MIS_TEXT,      0, IDM_RESET_DEFAULTS,   NULL, 0 },
  313.     { MIT_END, MIS_TEXT,      0, IDM_HIDE_CONTROLS,    NULL, 0 }
  314.   } ;
  315.  
  316.   static MENUITEM MenuSeparator =
  317.     { MIT_END, MIS_SEPARATOR, 0, 0, NULL, 0 } ;
  318.  
  319.   static MENUITEM MenuAbout =
  320.     { MIT_END, MIS_TEXT, 0, IDM_ABOUT, NULL, 0 } ;
  321.  
  322.   static MENUITEM MenuItem =
  323.     { MIT_END, MIS_TEXT, 0, 0, NULL, 0 } ;
  324.  
  325.   DATA *Data = (DATA *) data ;
  326.  
  327.   HPS hPS ;
  328.   HWND hwndFrame ;
  329.   HWND hwndSysMenu ;
  330.   HWND hwndSysSubMenu ;
  331.   SHORT i ;
  332.   SHORT idSysMenu ;
  333.   MENUITEM miSysMenu ;
  334.   PID pid ;
  335.   ULONG Size ;
  336.   char *Swappath ;
  337.   SWCNTRL swctl ;
  338.  
  339.  /***********************************************************************
  340.   * Get profile data.                            *
  341.   ***********************************************************************/
  342.  
  343.   GetProfile ( &Data->Profile ) ;
  344.  
  345.  /***********************************************************************
  346.   * Get the control window handles.                                     *
  347.   ***********************************************************************/
  348.  
  349.   hwndFrame = WinQueryWindow ( hwnd, QW_PARENT, FALSE ) ;
  350.  
  351.   Data->hwndSysMenu  = WinWindowFromID ( hwndFrame, FID_SYSMENU  ) ;
  352.   Data->hwndTitleBar = WinWindowFromID ( hwndFrame, FID_TITLEBAR ) ;
  353.   Data->hwndMinMax   = WinWindowFromID ( hwndFrame, FID_MINMAX   ) ;
  354.  
  355.  /***********************************************************************
  356.   * Add basic extensions to the system menu.                *
  357.   ***********************************************************************/
  358.  
  359.   hwndSysMenu = WinWindowFromID ( WinQueryWindow ( hwnd, QW_PARENT, FALSE ), FID_SYSMENU ) ;
  360.   idSysMenu = SHORT1FROMMR ( WinSendMsg ( hwndSysMenu, MM_ITEMIDFROMPOSITION, NULL, NULL ) ) ;
  361.   WinSendMsg ( hwndSysMenu, MM_QUERYITEM, MPFROM2SHORT(idSysMenu,FALSE), MPFROMP(&miSysMenu) ) ;
  362.   hwndSysSubMenu = miSysMenu.hwndSubMenu ;
  363.  
  364.   WinSendMsg ( hwndSysSubMenu, MM_INSERTITEM,
  365.     MPFROMP(&MenuSeparator), MPFROMP(NULL) ) ;
  366.  
  367.   for ( i=0; i<sizeof(MenuItems)/sizeof(MenuItems[0]); i++ )
  368.   {
  369.     WinSendMsg ( hwndSysSubMenu, MM_INSERTITEM, MPFROMP(MenuItems+i), MPFROMP(szMenuText[i]) ) ;
  370.   }
  371.  
  372.  /***********************************************************************
  373.   * Add display items as options to the system menu.            *
  374.   ***********************************************************************/
  375.  
  376.   WinSendMsg ( hwndSysSubMenu, MM_INSERTITEM,
  377.     MPFROMP(&MenuSeparator), MPFROMP(NULL) ) ;
  378.  
  379.   for ( i=0; i<Data->Profile.ItemCount; i++ )
  380.   {
  381.     ITEM *Item = & Data->Profile.Items [i] ;
  382.  
  383.     MenuItem.id = Item->MenuId ;
  384.     WinSendMsg ( hwndSysSubMenu, MM_INSERTITEM,
  385.       MPFROMP(&MenuItem), MPFROMP(Item->MenuOption) ) ;
  386.  
  387.     WinSendMsg ( Data->hwndSysMenu, MM_SETITEMATTR,
  388.       MPFROM2SHORT ( Item->MenuId, TRUE ),
  389.       MPFROM2SHORT ( MIA_CHECKED, Item->Flag ? MIA_CHECKED : FALSE ) ) ;
  390.   }
  391.  
  392.  /***********************************************************************
  393.   * Add 'About' to the system menu.                    *
  394.   ***********************************************************************/
  395.  
  396.   WinSendMsg ( hwndSysSubMenu, MM_INSERTITEM,
  397.     MPFROMP(&MenuSeparator), MPFROMP(NULL) ) ;
  398.  
  399.   WinSendMsg ( hwndSysSubMenu, MM_INSERTITEM,
  400.     MPFROMP(&MenuAbout), MPFROMP("About...") ) ;
  401.  
  402.  /***********************************************************************
  403.   * Start up a one-second timer.  Return error if unable to do so.      *
  404.   ***********************************************************************/
  405.  
  406.   if ( NOT WinStartTimer ( hAB, hwnd, ID_TIMER, 1000 ) )
  407.   {
  408.     WinMessageBox ( HWND_DESKTOP, hwnd, "ERROR: Too many clocks or timers",
  409.       "Memory Size", 0, MB_OK | MB_ICONEXCLAMATION ) ;
  410.     return ( MRFROMSHORT ( 1 ) ) ;
  411.   }
  412.  
  413.  /***********************************************************************
  414.   * Get the SWAPPATH statement from CONFIG.SYS.                         *
  415.   ***********************************************************************/
  416.  
  417.   Swappath = ScanSystemConfig ( "SWAPPATH" ) ;
  418.  
  419.   if ( Swappath == NULL )
  420.   {
  421.     Swappath = "C:\\OS2\\SYSTEM 0" ;
  422.   }
  423.  
  424.   strupr ( Swappath ) ;
  425.  
  426.   sscanf ( Swappath, "%s %i", Data->SwapPath, &Data->MinFree ) ;
  427.  
  428.  /***********************************************************************
  429.   * Find out where the spool work directory is.             *
  430.   ***********************************************************************/
  431.  
  432.   Data->SpoolPath = NULL ;
  433.  
  434.   if ( PrfQueryProfileSize ( HINI_PROFILE, "PM_SPOOLER", "DIR", &Size ) )
  435.   {
  436.     Data->SpoolPath = malloc ( (int)Size ) ;
  437.     if ( Data->SpoolPath )
  438.     {
  439.       if ( PrfQueryProfileData ( HINI_PROFILE, "PM_SPOOLER", "DIR", Data->SpoolPath, &Size ) )
  440.       {
  441.     BYTE *p ;
  442.     p = strchr ( Data->SpoolPath, ';' ) ;
  443.     if ( p )
  444.     {
  445.       *p = 0 ;
  446.     }
  447.       }
  448.       else
  449.       {
  450.     free ( Data->SpoolPath ) ;
  451.     Data->SpoolPath = FALSE ;
  452.       }
  453.     }
  454.   }
  455.  
  456.  /***********************************************************************
  457.   * Calibrate the load meter.                                           *
  458.   ***********************************************************************/
  459.  
  460.   Data->MaxCount = CalibrateLoad ( ) ;
  461.  
  462.   Data->TimingParms.hwndClient = hwnd ;
  463.   Data->TimingParms.Count = & Data->Counter ;
  464.   Data->TimingThread = _beginthread ( TimingThread,
  465.     NULL, 4000, &Data->TimingParms ) ;
  466.  
  467.   Data->CountingParms.Count = & Data->Counter ;
  468.   Data->CountingThread = _beginthread ( CountingThread,
  469.     NULL, 4000, &Data->CountingParms ) ;
  470.  
  471.  /***********************************************************************
  472.   * If not showing CPU load, suspend those threads.                     *
  473.   ***********************************************************************/
  474.  
  475.   if ( NOT Data->Profile.Items[ITEM_CPULOAD].Flag )
  476.   {
  477.     DosSuspendThread ( Data->TimingThread ) ;
  478.     DosSuspendThread ( Data->CountingThread ) ;
  479.   }
  480.  
  481.  /***********************************************************************
  482.   * Add the program to the system task list.                            *
  483.   ***********************************************************************/
  484.  
  485.   WinQueryWindowProcess ( hwndFrame, &pid, NULL ) ;
  486.  
  487.   swctl.hwnd = hwndFrame ;
  488.   swctl.hwndIcon = NULL ;
  489.   swctl.hprog = NULL ;
  490.   swctl.idProcess = pid ;
  491.   swctl.idSession = 0 ;
  492.   swctl.uchVisibility = SWL_VISIBLE ;
  493.   swctl.fbJump = SWL_JUMPABLE ;
  494.   strcpy ( swctl.szSwtitle, "System Resources" ) ;
  495.  
  496.   WinAddSwitchEntry ( &swctl ) ;
  497.  
  498.  /***********************************************************************
  499.   * Position & size the window.  For some reason, we must move and size *
  500.   *   the window to the saved position before applying the resizing    *
  501.   *   function as fine-tuning.    Maybe the positioning request fails if    *
  502.   *   the window has no size?                        *
  503.   ***********************************************************************/
  504.  
  505.   WinSetWindowPos ( hwndFrame, NULL,
  506.     Data->Profile.Position.x, Data->Profile.Position.y,
  507.     Data->Profile.Position.cx, Data->Profile.Position.cy,
  508.     SWP_SIZE | SWP_MOVE ) ;
  509.  
  510.   ResizeWindow ( hwnd, &Data->Profile ) ;
  511.  
  512.  /***********************************************************************
  513.   * Hide the controls if so configured.                                 *
  514.   ***********************************************************************/
  515.  
  516.   if ( Data->Profile.HideControls )
  517.   {
  518.     HideControls
  519.     (
  520.       TRUE,
  521.       hwndFrame,
  522.       Data->hwndSysMenu,
  523.       Data->hwndTitleBar,
  524.       Data->hwndMinMax
  525.     ) ;
  526.  
  527.     WinSendMsg ( Data->hwndSysMenu, MM_SETITEMATTR,
  528.       MPFROM2SHORT ( IDM_HIDE_CONTROLS, TRUE ),
  529.       MPFROM2SHORT ( MIA_CHECKED, Data->Profile.HideControls ? MIA_CHECKED : 0 ) ) ;
  530.   }
  531.  
  532.  /***********************************************************************
  533.   * Get the saved presentation parameters and reinstate them.           *
  534.   ***********************************************************************/
  535.  
  536.   if ( Data->Profile.fFontNameSize )
  537.   {
  538.     WinSetPresParam ( hwnd, PP_FONTNAMESIZE,
  539.       strlen(Data->Profile.FontNameSize)+1, Data->Profile.FontNameSize ) ;
  540.   }
  541.  
  542.   if ( Data->Profile.fBackColor )
  543.   {
  544.     WinSetPresParam ( hwnd, PP_BACKGROUNDCOLOR,
  545.       sizeof(Data->Profile.BackColor), &Data->Profile.BackColor ) ;
  546.   }
  547.  
  548.   if ( Data->Profile.fTextColor )
  549.   {
  550.     WinSetPresParam ( hwnd, PP_FOREGROUNDCOLOR,
  551.       sizeof(Data->Profile.TextColor), &Data->Profile.TextColor ) ;
  552.   }
  553.  
  554.   hPS = WinGetPS ( hwnd ) ;
  555.   GpiQueryFontMetrics ( hPS, sizeof(Data->FontMetrics), &Data->FontMetrics ) ;
  556.   WinReleasePS ( hPS ) ;
  557.  
  558.  /***********************************************************************
  559.   * Now that the window's in order, make it visible.                    *
  560.   ***********************************************************************/
  561.  
  562.   WinShowWindow ( hwndFrame, TRUE ) ;
  563.  
  564.  /***********************************************************************
  565.   * Success?  Return no error.                                          *
  566.   ***********************************************************************/
  567.  
  568.   return ( 0 ) ;
  569.  
  570.   hwnd = hwnd ;
  571.   msg = msg ;
  572.   mp1 = mp1 ;
  573.   mp2 = mp2 ;
  574. }
  575.  
  576. /************************************************************************
  577.  *                                                                      *
  578.  *      Destroy main window.                                            *
  579.  *                                                                      *
  580.  ************************************************************************/
  581.  
  582. static MRESULT APIENTRY Destroy
  583. (
  584.   HWND hwnd,
  585.   USHORT msg,
  586.   MPARAM mp1,
  587.   MPARAM mp2,
  588.   void *data
  589. )
  590. {
  591.  /***********************************************************************
  592.   *                             Declarations                            *
  593.   ***********************************************************************/
  594.  
  595.   DATA *Data = (DATA *) data ;
  596.  
  597.  /***********************************************************************
  598.   * Stop the timer.                                                     *
  599.   ***********************************************************************/
  600.  
  601.   WinStopTimer ( hAB, hwnd, ID_TIMER ) ;
  602.  
  603.  /***********************************************************************
  604.   * Suspend the CPU load threads.                                       *
  605.   ***********************************************************************/
  606.  
  607.   DosSuspendThread ( Data->TimingThread ) ;
  608.  
  609.   DosSuspendThread ( Data->CountingThread ) ;
  610.  
  611.   return ( 0 ) ;
  612.  
  613.   hwnd = hwnd ;
  614.   msg = msg ;
  615.   mp1 = mp1 ;
  616.   mp2 = mp2 ;
  617. }
  618.  
  619. /************************************************************************
  620.  *                                                                      *
  621.  *      Process window resize message.                                  *
  622.  *                                                                      *
  623.  ************************************************************************/
  624.  
  625. static MRESULT APIENTRY Size
  626. (
  627.   HWND hwnd,
  628.   USHORT msg,
  629.   MPARAM mp1,
  630.   MPARAM mp2,
  631.   void *data
  632. )
  633. {
  634.  /***********************************************************************
  635.   *                             Declarations                            *
  636.   ***********************************************************************/
  637.  
  638.   DATA *Data = (DATA *) data ;
  639.  
  640.   HWND hwndFrame ;
  641.   SWP Position ;
  642.  
  643.  /***********************************************************************
  644.   * Find out the window's new position and size.                        *
  645.   ***********************************************************************/
  646.  
  647.   hwndFrame = WinQueryWindow ( hwnd, QW_PARENT, FALSE ) ;
  648.  
  649.   WinQueryWindowPos ( hwndFrame, &Position ) ;
  650.  
  651.   if ( NOT ( Position.fs & SWP_MINIMIZE )
  652.     AND NOT ( Position.fs & SWP_MAXIMIZE ) )
  653.   {
  654.     Data->Profile.Position.x = Position.x ;
  655.     Data->Profile.Position.y = Position.y ;
  656.  
  657.     Data->Profile.Position.cx = Position.cx ;
  658.     Data->Profile.Position.cy = Position.cy ;
  659.   }
  660.  
  661.   Data->Profile.Position.fs = Position.fs ;
  662.  
  663.  /***********************************************************************
  664.   * We're done.                                                         *
  665.   ***********************************************************************/
  666.  
  667.   return ( 0 ) ;
  668.  
  669.   hwnd = hwnd ;
  670.   msg = msg ;
  671.   mp1 = mp1 ;
  672.   mp2 = mp2 ;
  673. }
  674.  
  675. /************************************************************************
  676.  *                                                                      *
  677.  *      Process SAVE APPLICATION message.                               *
  678.  *                                                                      *
  679.  ************************************************************************/
  680.  
  681. static MRESULT APIENTRY SaveApplication
  682. (
  683.   HWND hwnd,
  684.   USHORT msg,
  685.   MPARAM mp1,
  686.   MPARAM mp2,
  687.   void *data
  688. )
  689. {
  690.  /***********************************************************************
  691.   *                             Declarations                            *
  692.   ***********************************************************************/
  693.  
  694.   DATA *Data = (DATA *) data ;
  695.  
  696.  /***********************************************************************
  697.   * Call function to put all profile data out to the system.        *
  698.   ***********************************************************************/
  699.  
  700.   PutProfile ( &Data->Profile ) ;
  701.  
  702.  /***********************************************************************
  703.   * We're done.  Let the system complete default processing.            *
  704.   ***********************************************************************/
  705.  
  706.   return ( WinDefWindowProc ( hwnd, msg, mp1, mp2 ) ) ;
  707.  
  708.   hwnd = hwnd ;
  709.   msg = msg ;
  710.   mp1 = mp1 ;
  711.   mp2 = mp2 ;
  712. }
  713.  
  714. /************************************************************************
  715.  *                                                                      *
  716.  *      Process timer message.                                          *
  717.  *                                                                      *
  718.  ************************************************************************/
  719.  
  720. static MRESULT APIENTRY Timer
  721. (
  722.   HWND hwnd,
  723.   USHORT msg,
  724.   MPARAM mp1,
  725.   MPARAM mp2,
  726.   void *data
  727. )
  728. {
  729.  /***********************************************************************
  730.   *                             Declarations                            *
  731.   ***********************************************************************/
  732.  
  733.   DATA *Data = (DATA *) data ;
  734.  
  735.  /***********************************************************************
  736.   * Update the window and return.                    *
  737.   ***********************************************************************/
  738.  
  739.   UpdateWindow ( hwnd, Data, FALSE ) ;
  740.  
  741.   return ( 0 ) ;
  742.  
  743.   hwnd = hwnd ;
  744.   msg = msg ;
  745.   mp1 = mp1 ;
  746.   mp2 = mp2 ;
  747. }
  748.  
  749. /************************************************************************
  750.  *                                                                      *
  751.  *      Repaint entire window.                                          *
  752.  *                                                                      *
  753.  ************************************************************************/
  754.  
  755. static MRESULT APIENTRY Paint
  756. (
  757.   HWND hwnd,
  758.   USHORT msg,
  759.   MPARAM mp1,
  760.   MPARAM mp2,
  761.   void *data
  762. )
  763. {
  764.  /***********************************************************************
  765.   *                             Declarations                            *
  766.   ***********************************************************************/
  767.  
  768.   DATA *Data = (DATA *) data ;
  769.  
  770.   HPS hPS ;
  771.   RECTL Rectangle ;
  772.  
  773.  /***********************************************************************
  774.   * Get presentation space and make it use RGB colors.                  *
  775.   ***********************************************************************/
  776.  
  777.   hPS = WinBeginPaint ( hwnd, NULL, NULL ) ;
  778.   GpiCreateLogColorTable ( hPS, LCOL_RESET, LCOLF_RGB, 0L, 0L, NULL ) ;
  779.  
  780.  /***********************************************************************
  781.   * Clear the window.                                                   *
  782.   ***********************************************************************/
  783.  
  784.   WinQueryWindowRect ( hwnd, &Rectangle ) ;
  785.  
  786.   GpiMove ( hPS, (PPOINTL) &Rectangle.xLeft ) ;
  787.   GpiSetColor ( hPS, Data->Profile.BackColor ) ;
  788.   GpiBox ( hPS, DRO_FILL, (PPOINTL) &Rectangle.xRight, 0L, 0L ) ;
  789.  
  790.  /***********************************************************************
  791.   * Release presentation space.                     *
  792.   ***********************************************************************/
  793.  
  794.   WinEndPaint ( hPS ) ;
  795.  
  796.  /***********************************************************************
  797.   * Update the window and return.                    *
  798.   ***********************************************************************/
  799.  
  800.   UpdateWindow ( hwnd, Data, TRUE ) ;
  801.  
  802.   return ( 0 ) ;
  803.  
  804.   hwnd = hwnd ;
  805.   msg = msg ;
  806.   mp1 = mp1 ;
  807.   mp2 = mp2 ;
  808. }
  809.  
  810. /************************************************************************
  811.  *                                                                      *
  812.  *      Process commands received by Main Window                        *
  813.  *                                                                      *
  814.  ************************************************************************/
  815.  
  816. static MRESULT APIENTRY Command
  817. (
  818.   HWND hwnd,
  819.   USHORT msg,
  820.   MPARAM mp1,
  821.   MPARAM mp2,
  822.   void *data
  823. )
  824. {
  825.  /***********************************************************************
  826.   * Local Declarations                                                  *
  827.   ***********************************************************************/
  828.  
  829.   DATA *Data = (DATA *) data ;
  830.  
  831.   USHORT Command ;
  832.   short i ;
  833.  
  834.  /***********************************************************************
  835.   * Process indicated command . . .                                     *
  836.   ***********************************************************************/
  837.  
  838.   Command = SHORT1FROMMP ( mp1 ) ;
  839.  
  840.  /***********************************************************************
  841.   * Process display item commands.                    *
  842.   ***********************************************************************/
  843.  
  844.   for ( i=0; i<Data->Profile.ItemCount; i++ )
  845.   {
  846.     ITEM *Item = & Data->Profile.Items [i] ;
  847.  
  848.     if ( Command == Item->MenuId )
  849.     {
  850.       Item->Flag = Item->Flag ? FALSE : TRUE ;
  851.  
  852.       WinSendMsg ( Data->hwndSysMenu, MM_SETITEMATTR,
  853.     MPFROM2SHORT ( Item->MenuId, TRUE ),
  854.     MPFROM2SHORT ( MIA_CHECKED, Item->Flag ? MIA_CHECKED : 0 ) ) ;
  855.  
  856.       ResizeWindow ( hwnd, &Data->Profile ) ;
  857.  
  858.       if ( i == ITEM_CPULOAD )
  859.       {
  860.     if ( Item->Flag )
  861.     {
  862.       DosResumeThread ( Data->TimingThread ) ;
  863.       DosResumeThread ( Data->CountingThread ) ;
  864.     }
  865.     else
  866.     {
  867.       DosSuspendThread ( Data->TimingThread ) ;
  868.       DosSuspendThread ( Data->CountingThread ) ;
  869.     }
  870.       }
  871.  
  872.       return ( MRFROMSHORT ( 0 ) ) ;
  873.     }
  874.   }
  875.  
  876.  /***********************************************************************
  877.   * Process fixed commands . . .                    *
  878.   ***********************************************************************/
  879.  
  880.   switch ( Command )
  881.   {
  882.  
  883.    /*********************************************************************
  884.     * End the program.                                                  *
  885.     *********************************************************************/
  886.  
  887.     case IDM_EXIT:
  888.     {
  889.       WinSendMsg ( hwnd, WM_CLOSE, 0L, 0L );
  890.       break ;
  891.     }
  892.  
  893.    /*********************************************************************
  894.     * Save application defaults.                                        *
  895.     *********************************************************************/
  896.  
  897.     case IDM_SAVE_APPLICATION:
  898.     {
  899.       WinSendMsg ( hwnd, WM_SAVEAPPLICATION, 0L, 0L );
  900.       break ;
  901.     }
  902.  
  903.    /*********************************************************************
  904.     * Reset application defaults.                    *
  905.     *********************************************************************/
  906.  
  907.     case IDM_RESET_DEFAULTS:
  908.     {
  909.       PrfWriteProfileData ( HINI_USERPROFILE, PROGRAM_NAME, NULL, NULL, 0 ) ;
  910.       WinRemovePresParam ( hwnd, PP_FONTNAMESIZE ) ;
  911.       WinRemovePresParam ( hwnd, PP_FOREGROUNDCOLOR ) ;
  912.       WinRemovePresParam ( hwnd, PP_BACKGROUNDCOLOR ) ;
  913.       break ;
  914.     }
  915.  
  916.    /*********************************************************************
  917.     * Hide Controls.                                                    *
  918.     *********************************************************************/
  919.  
  920.     case IDM_HIDE_CONTROLS:
  921.     {
  922.       Data->Profile.HideControls = Data->Profile.HideControls ? FALSE : TRUE ;
  923.  
  924.       HideControls
  925.       (
  926.     Data->Profile.HideControls,
  927.     WinQueryWindow ( hwnd, QW_PARENT, FALSE ),
  928.     Data->hwndSysMenu,
  929.     Data->hwndTitleBar,
  930.     Data->hwndMinMax
  931.       ) ;
  932.  
  933.       WinSendMsg ( Data->hwndSysMenu, MM_SETITEMATTR,
  934.         MPFROM2SHORT ( IDM_HIDE_CONTROLS, TRUE ),
  935.     MPFROM2SHORT ( MIA_CHECKED, Data->Profile.HideControls ? MIA_CHECKED : 0 ) ) ;
  936.  
  937.       break ;
  938.     }
  939.  
  940.    /*********************************************************************
  941.     * Display copyright information.                                    *
  942.     *********************************************************************/
  943.  
  944.     case IDM_ABOUT:
  945.     {
  946.       ABOUT_PARMS Parms ;
  947.  
  948.       Parms.id = IDD_ABOUT ;
  949.       Parms.hwndHelp = hwndHelp ;
  950.  
  951.       WinDlgBox ( HWND_DESKTOP, hwnd, AboutProcessor,
  952.         0, IDD_ABOUT, &Parms ) ;
  953.  
  954.       break ;
  955.     }
  956.  
  957.    /*********************************************************************
  958.     * None of the above?  Beep a complaint.                             *
  959.     *********************************************************************/
  960.  
  961.     default:
  962.     {
  963.       WinAlarm ( HWND_DESKTOP, WA_NOTE ) ;
  964.       break ;
  965.     }
  966.   }
  967.  
  968.   return ( MRFROMSHORT ( 0 ) ) ;
  969.  
  970.   hwnd = hwnd ;  msg = msg ;  mp1 = mp1 ;  mp2 = mp2 ;  data = data ;
  971. }
  972.  
  973. /************************************************************************
  974.  *                                                                      *
  975.  *      Process Mouse Button being pressed.                             *
  976.  *                                                                      *
  977.  ************************************************************************/
  978.  
  979. static MRESULT APIENTRY ButtonDown
  980. (
  981.   HWND hwnd,
  982.   USHORT msg,
  983.   MPARAM mp1,
  984.   MPARAM mp2,
  985.   void *data
  986. )
  987. {
  988.  /***********************************************************************
  989.   * Local Declarations                                                  *
  990.   ***********************************************************************/
  991.  
  992.   DATA *Data = (DATA *) data ;
  993.  
  994.   HWND hwndFrame ;
  995.   SWP Position ;
  996.   TRACKINFO TrackInfo ;
  997.  
  998.  /***********************************************************************
  999.   * Determine the new window position.                                  *
  1000.   ***********************************************************************/
  1001.  
  1002.   memset ( &TrackInfo, 0, sizeof(TrackInfo) ) ;
  1003.  
  1004.   TrackInfo.cxBorder = 1 ;
  1005.   TrackInfo.cyBorder = 1 ;
  1006.   TrackInfo.cxGrid = 1 ;
  1007.   TrackInfo.cyGrid = 1 ;
  1008.   TrackInfo.cxKeyboard = 8 ;
  1009.   TrackInfo.cyKeyboard = 8 ;
  1010.  
  1011.   hwndFrame = WinQueryWindow ( hwnd, QW_PARENT, FALSE ) ;
  1012.  
  1013.   WinQueryWindowPos ( hwndFrame, &Position ) ;
  1014.   TrackInfo.rclTrack.xLeft   = Position.x ;
  1015.   TrackInfo.rclTrack.xRight  = Position.x + Position.cx ;
  1016.   TrackInfo.rclTrack.yBottom = Position.y ;
  1017.   TrackInfo.rclTrack.yTop    = Position.y + Position.cy ;
  1018.  
  1019.   WinQueryWindowPos ( HWND_DESKTOP, &Position ) ;
  1020.   TrackInfo.rclBoundary.xLeft   = Position.x ;
  1021.   TrackInfo.rclBoundary.xRight  = Position.x + Position.cx ;
  1022.   TrackInfo.rclBoundary.yBottom = Position.y ;
  1023.   TrackInfo.rclBoundary.yTop    = Position.y + Position.cy ;
  1024.  
  1025.   TrackInfo.ptlMinTrackSize.x = 0 ;
  1026.   TrackInfo.ptlMinTrackSize.y = 0 ;
  1027.   TrackInfo.ptlMaxTrackSize.x = Position.cx ;
  1028.   TrackInfo.ptlMaxTrackSize.y = Position.cy ;
  1029.  
  1030.   TrackInfo.fs = TF_MOVE | TF_STANDARD | TF_ALLINBOUNDARY ;
  1031.  
  1032.   if ( WinTrackRect ( HWND_DESKTOP, NULL, &TrackInfo ) )
  1033.   {
  1034.     WinSetWindowPos ( hwndFrame, NULL,
  1035.       (SHORT) TrackInfo.rclTrack.xLeft,
  1036.       (SHORT) TrackInfo.rclTrack.yBottom,
  1037.       0, 0, SWP_MOVE ) ;
  1038.   }
  1039.  
  1040.  /***********************************************************************
  1041.   * Return through the default processor, letting window activation     *
  1042.   *   and other system functions occur.                                 *
  1043.   ***********************************************************************/
  1044.  
  1045.   return ( WinDefWindowProc ( hwnd, msg, mp1, mp2 ) ) ;
  1046.  
  1047.   hwnd = hwnd ;  msg = msg ;  mp1 = mp1 ;  mp2 = mp2 ;  data = data ;
  1048. }
  1049.  
  1050. /************************************************************************
  1051.  *                                                                      *
  1052.  *      Process Mouse Button having been double-clicked.                *
  1053.  *                                                                      *
  1054.  ************************************************************************/
  1055.  
  1056. static MRESULT APIENTRY ButtonDblClick
  1057. (
  1058.   HWND hwnd,
  1059.   USHORT msg,
  1060.   MPARAM mp1,
  1061.   MPARAM mp2,
  1062.   void *data
  1063. )
  1064. {
  1065.  /***********************************************************************
  1066.   * Local Declarations                                                  *
  1067.   ***********************************************************************/
  1068.  
  1069.   DATA *Data = (DATA *) data ;
  1070.  
  1071.  /***********************************************************************
  1072.   * Send message to self to stop hiding the controls.                   *
  1073.   ***********************************************************************/
  1074.  
  1075.   WinPostMsg ( hwnd, WM_COMMAND,
  1076.     MPFROM2SHORT ( IDM_HIDE_CONTROLS, 0 ),
  1077.     MPFROM2SHORT ( CMDSRC_OTHER, TRUE ) ) ;
  1078.  
  1079.  /***********************************************************************
  1080.   * Return through the default processor, letting window activation     *
  1081.   *   and other system functions occur.                                 *
  1082.   ***********************************************************************/
  1083.  
  1084.   return ( WinDefWindowProc ( hwnd, msg, mp1, mp2 ) ) ;
  1085.  
  1086.   hwnd = hwnd ;  msg = msg ;  mp1 = mp1 ;  mp2 = mp2 ;  data = data ;
  1087. }
  1088.  
  1089. /************************************************************************
  1090.  *                                                                      *
  1091.  *      Process Presentation Parameter Changed notification.            *
  1092.  *                                                                      *
  1093.  ************************************************************************/
  1094.  
  1095. static MRESULT APIENTRY PresParamChanged
  1096. (
  1097.   HWND hwnd,
  1098.   USHORT msg,
  1099.   MPARAM mp1,
  1100.   MPARAM mp2,
  1101.   void *data
  1102. )
  1103. {
  1104.  /***********************************************************************
  1105.   * Local Declarations                                                  *
  1106.   ***********************************************************************/
  1107.  
  1108.   DATA *Data = (DATA *) data ;
  1109.  
  1110.   HPS hPS ;
  1111.   ULONG ppid ;
  1112.  
  1113.  /***********************************************************************
  1114.   * Get the presentation parameter that changed.            *
  1115.   ***********************************************************************/
  1116.  
  1117.   switch ( LONGFROMMP(mp1) )
  1118.   {
  1119.  
  1120.    /*********************************************************************
  1121.     * If font, note the fact that we now have a font to be saved as    *
  1122.     *    part of the configuration.  Get the font metrics and resize    *
  1123.     *    the window appropriately.                    *
  1124.     *********************************************************************/
  1125.  
  1126.     case PP_FONTNAMESIZE:
  1127.     {
  1128.       if ( WinQueryPresParam ( hwnd, PP_FONTNAMESIZE, 0, &ppid,
  1129.     sizeof(Data->Profile.FontNameSize), &Data->Profile.FontNameSize,
  1130.     0 ) )
  1131.       {
  1132.     Data->Profile.fFontNameSize = TRUE ;
  1133.       }
  1134.       else
  1135.       {
  1136.     strcpy ( Data->Profile.FontNameSize, "" ) ;
  1137.     Data->Profile.fFontNameSize = FALSE ;
  1138.     PrfWriteProfileData ( HINI_USERPROFILE, PROGRAM_NAME, "FontNameSize", NULL, 0 ) ;
  1139.       }
  1140.       hPS = WinGetPS ( hwnd ) ;
  1141.       GpiQueryFontMetrics ( hPS, sizeof(Data->FontMetrics), &Data->FontMetrics ) ;
  1142.       WinReleasePS ( hPS ) ;
  1143.       ResizeWindow ( hwnd, &Data->Profile ) ;
  1144.       break ;
  1145.     }
  1146.  
  1147.    /*********************************************************************
  1148.     * If background color, note the fact and repaint the window.    *
  1149.     *********************************************************************/
  1150.  
  1151.     case PP_BACKGROUNDCOLOR:
  1152.     {
  1153.       if ( WinQueryPresParam ( hwnd, PP_BACKGROUNDCOLOR, 0, &ppid,
  1154.     sizeof(Data->Profile.BackColor), &Data->Profile.BackColor, 0 ) )
  1155.       {
  1156.     Data->Profile.fBackColor = TRUE ;
  1157.     WinInvalidateRect ( hwnd, NULL, TRUE ) ;
  1158.       }
  1159.       else
  1160.       {
  1161.     Data->Profile.BackColor = WinQuerySysColor ( HWND_DESKTOP, SYSCLR_WINDOW, 0L ) ;
  1162.     Data->Profile.fBackColor = FALSE ;
  1163.     PrfWriteProfileData ( HINI_USERPROFILE, PROGRAM_NAME, "BackgroundColor", NULL, 0 ) ;
  1164.       }
  1165.       break ;
  1166.     }
  1167.  
  1168.    /*********************************************************************
  1169.     * If foreground color, note the fact and repaint the window.    *
  1170.     *********************************************************************/
  1171.  
  1172.     case PP_FOREGROUNDCOLOR:
  1173.     {
  1174.       if ( WinQueryPresParam ( hwnd, PP_FOREGROUNDCOLOR, 0, &ppid,
  1175.     sizeof(Data->Profile.TextColor), &Data->Profile.TextColor, 0 ) )
  1176.       {
  1177.     Data->Profile.fTextColor = TRUE ;
  1178.     WinInvalidateRect ( hwnd, NULL, TRUE ) ;
  1179.       }
  1180.       else
  1181.       {
  1182.     Data->Profile.TextColor = WinQuerySysColor ( HWND_DESKTOP, SYSCLR_OUTPUTTEXT, 0L ) ;
  1183.     Data->Profile.fTextColor = FALSE ;
  1184.     PrfWriteProfileData ( HINI_USERPROFILE, PROGRAM_NAME, "ForegroundColor", NULL, 0 ) ;
  1185.       }
  1186.       break ;
  1187.     }
  1188.   }
  1189.  
  1190.  /***********************************************************************
  1191.   * Return through the default processor, letting window activation     *
  1192.   *   and other system functions occur.                                 *
  1193.   ***********************************************************************/
  1194.  
  1195.   return ( WinDefWindowProc ( hwnd, msg, mp1, mp2 ) ) ;
  1196.  
  1197.   hwnd = hwnd ;  msg = msg ;  mp1 = mp1 ;  mp2 = mp2 ;  data = data ;
  1198. }
  1199.  
  1200. /************************************************************************
  1201.  *                                                                      *
  1202.  *      Process Semaphore 1 notification.                               *
  1203.  *                                                                      *
  1204.  ************************************************************************/
  1205.  
  1206. static MRESULT APIENTRY Semaphore1
  1207. (
  1208.   HWND hwnd,
  1209.   USHORT msg,
  1210.   MPARAM mp1,
  1211.   MPARAM mp2,
  1212.   void *data
  1213. )
  1214. {
  1215.  /***********************************************************************
  1216.   * Local Declarations                                                  *
  1217.   ***********************************************************************/
  1218.  
  1219.   DATA *Data = (DATA *) data ;
  1220.  
  1221.   ULONG Count ;
  1222.  
  1223.  /***********************************************************************
  1224.   * Compute CPU load.                                                   *
  1225.   ***********************************************************************/
  1226.  
  1227.   Count = min ( LONGFROMMP(mp1), Data->MaxCount ) ;
  1228.  
  1229.   Data->NewLoad = ( Count * 200 + 50 ) / Data->MaxCount ;
  1230.  
  1231.   if ( Data->NewLoad > 100 )
  1232.     Data->NewLoad = 0 ;
  1233.   else
  1234.     Data->NewLoad = 100 - Data->NewLoad ;
  1235.  
  1236.  /***********************************************************************
  1237.   * Return successful.                                                  *
  1238.   ***********************************************************************/
  1239.  
  1240.   return ( 0 ) ;
  1241.  
  1242.   hwnd = hwnd ;  msg = msg ;  mp1 = mp1 ;  mp2 = mp2 ;  data = data ;
  1243. }
  1244.  
  1245. /************************************************************************
  1246.  *                                                                      *
  1247.  *      Process Query for Keys Help resource id.                        *
  1248.  *                                                                      *
  1249.  ************************************************************************/
  1250.  
  1251. static MRESULT APIENTRY QueryKeysHelp
  1252. (
  1253.   HWND hwnd,
  1254.   USHORT msg,
  1255.   MPARAM mp1,
  1256.   MPARAM mp2,
  1257.   void *data
  1258. )
  1259. {
  1260.  /***********************************************************************
  1261.   * Local Declarations                                                  *
  1262.   ***********************************************************************/
  1263.  
  1264.   DATA *Data = (DATA *) data ;
  1265.  
  1266.  /***********************************************************************
  1267.   * Simply return the ID of the Keys Help panel.                        *
  1268.   ***********************************************************************/
  1269.  
  1270.   return ( (MRESULT) IDM_KEYS_HELP ) ;
  1271.  
  1272.   hwnd = hwnd ;  msg = msg ;  mp1 = mp1 ;  mp2 = mp2 ;  data = data ;
  1273. }
  1274.  
  1275. /************************************************************************
  1276.  *                                                                      *
  1277.  *      Process Help Manager Error                                      *
  1278.  *                                                                      *
  1279.  ************************************************************************/
  1280.  
  1281. static MRESULT APIENTRY HelpError
  1282. (
  1283.   HWND hwnd,
  1284.   USHORT msg,
  1285.   MPARAM mp1,
  1286.   MPARAM mp2,
  1287.   void *data
  1288. )
  1289. {
  1290.  /***********************************************************************
  1291.   * Local Declarations                                                  *
  1292.   ***********************************************************************/
  1293.  
  1294.   static struct
  1295.   {
  1296.     ULONG Error ;
  1297.     PSZ Message ;
  1298.   }
  1299.   HelpErrors [] =
  1300.   {
  1301.     { HMERR_NO_FRAME_WND_IN_CHAIN,     "No frame window in chain."                   },
  1302.     { HMERR_INVALID_ASSOC_APP_WND,     "Invalid window handle associated."           },
  1303.     { HMERR_INVALID_ASSOC_HELP_INST,   "Invalid help instance associated."           },
  1304.     { HMERR_INVALID_DESTROY_HELP_INST, "Invalid window handle to deassociate."       },
  1305.     { HMERR_NO_HELP_INST_IN_CHAIN,     "No help instance in window chain."           },
  1306.     { HMERR_INVALID_HELP_INSTANCE_HDL, "Invalid help instance handle."               },
  1307.     { HMERR_INVALID_QUERY_APP_WND,     "Invalid application window handle in query." },
  1308.     { HMERR_HELP_INST_CALLED_INVALID,  "Help instance called invalid."               },
  1309.     { HMERR_HELPTABLE_UNDEFINE,        "Help table undefined."                       },
  1310.     { HMERR_HELP_INSTANCE_UNDEFINE,    "Help instance undefined."                    },
  1311.     { HMERR_HELPITEM_NOT_FOUND,        "Help item not found."                        },
  1312.     { HMERR_INVALID_HELPSUBITEM_SIZE,  "Invalid help subitem size."                  },
  1313.     { HMERR_HELPSUBITEM_NOT_FOUND,     "Help subitem not found."                     },
  1314.     { HMERR_INDEX_NOT_FOUND,           "No index in library file."                   },
  1315.     { HMERR_CONTENT_NOT_FOUND,         "Table of contents not found."                },
  1316.     { HMERR_OPEN_LIB_FILE,             "Unable to open help library."                },
  1317.     { HMERR_READ_LIB_FILE,             "Unable to read help library."                },
  1318.     { HMERR_CLOSE_LIB_FILE,            "Unable to close help library."               },
  1319.     { HMERR_INVALID_LIB_FILE,          "Help library has invalid format."            },
  1320.     { HMERR_NO_MEMORY,                 "Out of memory."                              },
  1321.     { HMERR_ALLOCATE_SEGMENT,          "Unable to allocate segment."                 },
  1322.     { HMERR_FREE_MEMORY,               "Unable to release memory."                   },
  1323.     { HMERR_PANEL_NOT_FOUND,           "Help panel not found."                       },
  1324.     { HMERR_DATABASE_NOT_OPEN,         "Help database not open."                     },
  1325.     { 0,                               "--- Unknown Error ---"                       }
  1326.   } ;
  1327.  
  1328.   DATA *Data = (DATA *) data ;
  1329.  
  1330.   ULONG ErrorCode = (ULONG) LONGFROMMP ( mp1 ) ;
  1331.   int Index ;
  1332.  
  1333.  /***********************************************************************
  1334.   * Find the error code in the message table.                           *
  1335.   ***********************************************************************/
  1336.  
  1337.   Index = 0 ;
  1338.   while ( HelpErrors[Index].Error
  1339.     AND ( HelpErrors[Index].Error != ErrorCode ) )
  1340.   {
  1341.     Index ++ ;
  1342.   }
  1343.  
  1344.  /***********************************************************************
  1345.   * Display the error message.                                          *
  1346.   ***********************************************************************/
  1347.  
  1348.   WinMessageBox
  1349.   (
  1350.     HWND_DESKTOP,
  1351.     hwnd,
  1352.     HelpErrors[Index].Message,
  1353.     "Help Manager Error",
  1354.     0,
  1355.     MB_OK | MB_WARNING
  1356.   ) ;
  1357.  
  1358.  /***********************************************************************
  1359.   * Return zero, indicating that the message was processed.             *
  1360.   ***********************************************************************/
  1361.  
  1362.   return ( MRFROMSHORT ( 0 ) ) ;
  1363.  
  1364.   hwnd = hwnd ;  msg = msg ;  mp1 = mp1 ;  mp2 = mp2 ;  data = data ;
  1365. }
  1366.  
  1367. /************************************************************************
  1368.  *                                                                      *
  1369.  *      Process "Extended Help Undefined" notification                  *
  1370.  *                                                                      *
  1371.  ************************************************************************/
  1372.  
  1373. static MRESULT APIENTRY ExtHelpUndefined
  1374. (
  1375.   HWND hwnd,
  1376.   USHORT msg,
  1377.   MPARAM mp1,
  1378.   MPARAM mp2,
  1379.   void *data
  1380. )
  1381. {
  1382.  /***********************************************************************
  1383.   * Local Declarations                                                  *
  1384.   ***********************************************************************/
  1385.  
  1386.   DATA *Data = (DATA *) data ;
  1387.  
  1388.  /***********************************************************************
  1389.   * Display the error message.                                          *
  1390.   ***********************************************************************/
  1391.  
  1392.   WinMessageBox
  1393.   (
  1394.     HWND_DESKTOP,
  1395.     hwnd,
  1396.     "Extended help undefined.",
  1397.     "Help Manager Error",
  1398.     0,
  1399.     MB_OK | MB_WARNING
  1400.   ) ;
  1401.  
  1402.  /***********************************************************************
  1403.   * Return zero, indicating that the message was processed.             *
  1404.   ***********************************************************************/
  1405.  
  1406.   return ( MRFROMSHORT ( 0 ) ) ;
  1407.  
  1408.   hwnd = hwnd ;  msg = msg ;  mp1 = mp1 ;  mp2 = mp2 ;  data = data ;
  1409. }
  1410.  
  1411. /************************************************************************
  1412.  *                                                                      *
  1413.  *      Process "Help Subitem Not Found" notification                   *
  1414.  *                                                                      *
  1415.  ************************************************************************/
  1416.  
  1417. static MRESULT APIENTRY HelpSubitemNotFound
  1418. (
  1419.   HWND hwnd,
  1420.   USHORT msg,
  1421.   MPARAM mp1,
  1422.   MPARAM mp2,
  1423.   void *data
  1424. )
  1425. {
  1426.  /***********************************************************************
  1427.   * Local Declarations                                                  *
  1428.   ***********************************************************************/
  1429.  
  1430.   DATA *Data = (DATA *) data ;
  1431.  
  1432.   int i ;
  1433.   BYTE Message [200] ;
  1434.   PSZ Mode ;
  1435.   USHORT Subtopic ;
  1436.   USHORT Topic ;
  1437.  
  1438.  /***********************************************************************
  1439.   * Format the error message.                                           *
  1440.   ***********************************************************************/
  1441.  
  1442.   Topic = (USHORT) SHORT1FROMMP ( mp2 ) ;
  1443.   Subtopic = (USHORT) SHORT2FROMMP ( mp2 ) ;
  1444.  
  1445.   i = SHORT1FROMMP ( mp1 ) ;
  1446.  
  1447.   switch ( i )
  1448.   {
  1449.     case HLPM_FRAME:
  1450.       Mode = "Frame" ;
  1451.       break ;
  1452.  
  1453.     case HLPM_MENU:
  1454.       Mode = "Menu" ;
  1455.       break ;
  1456.  
  1457.     case HLPM_WINDOW:
  1458.       Mode = "Window" ;
  1459.       break ;
  1460.  
  1461.     default:
  1462.       Mode = "Unknown" ;
  1463.   }
  1464.  
  1465.   sprintf
  1466.   (
  1467.     Message,
  1468.     "Help subitem not found:\n"
  1469.     "Mode='%s'\n"
  1470.     "Topic=%u\n"
  1471.     "Subtopic=%u",
  1472.     Mode, Topic, Subtopic
  1473.   ) ;
  1474.  
  1475.  /***********************************************************************
  1476.   * Display the error message.                                          *
  1477.   ***********************************************************************/
  1478.  
  1479.   WinMessageBox
  1480.   (
  1481.     HWND_DESKTOP,
  1482.     hwnd,
  1483.     Message,
  1484.     "Help Manager Error",
  1485.     0,
  1486.     MB_OK | MB_WARNING
  1487.   ) ;
  1488.  
  1489.  /***********************************************************************
  1490.   * Return zero, indicating that the message was processed.             *
  1491.   ***********************************************************************/
  1492.  
  1493.   return ( MRFROMSHORT ( 0 ) ) ;
  1494.  
  1495.   hwnd = hwnd ;  msg = msg ;  mp1 = mp1 ;  mp2 = mp2 ;  data = data ;
  1496. }
  1497.  
  1498. /************************************************************************
  1499.  *                                                                      *
  1500.  *                 Get Profile Data                *
  1501.  *                                                                      *
  1502.  ************************************************************************/
  1503.  
  1504. static void GetProfile ( PROFILE *Profile )
  1505. {
  1506.  /***********************************************************************
  1507.   * Local Declarations                            *
  1508.   ***********************************************************************/
  1509.  
  1510.   #define ITEM_BASE_COUNT    5
  1511.   #define MAX_DRIVES        26
  1512.  
  1513.   static ITEM Items [ ITEM_BASE_COUNT + MAX_DRIVES ] =
  1514.   {
  1515.     {
  1516.       "ShowMemory",   TRUE, "Available memory",     0L,
  1517.       "Show Memory Free",     IDM_SHOW_MEMORY,
  1518.       ComputeFreeMemory, 0, 1024, 'K'
  1519.     },
  1520.  
  1521.     {
  1522.       "ShowSwapsize", TRUE, "Swap-file size",        0L,
  1523.       "Show Swapfile Size",   IDM_SHOW_SWAPSIZE,
  1524.       ComputeSwapSize,     0, 1024, 'K'
  1525.     },
  1526.  
  1527.     {
  1528.       "ShowSwapfree", TRUE, "Available swap space", 0L,
  1529.       "Show Swap Space Free", IDM_SHOW_SWAPFREE,
  1530.       ComputeSwapFree,     0, 1024, 'K'
  1531.     },
  1532.  
  1533.     {
  1534.       "ShowSpoolSize",TRUE, "Spool-file size",        0L,
  1535.       "Show Spool Size",      IDM_SHOW_SPOOLSIZE,
  1536.       ComputeSpoolSize,  0, 1024, 'K'
  1537.     },
  1538.  
  1539.     {
  1540.       "ShowCpuLoad",  TRUE, "CPU Load",         0L,
  1541.       "Show CPU Load",          IDM_SHOW_CPULOAD,
  1542.       ComputeCpuLoad,     0, 0,      '%'
  1543.     }
  1544.   } ;
  1545.  
  1546.   int Count ;
  1547.   USHORT Drive ;
  1548.   ULONG Drives ;
  1549.   int i ;
  1550.   ULONG Size ;
  1551.  
  1552.  /***********************************************************************
  1553.   * Add items for each drive on the system.                *
  1554.   ***********************************************************************/
  1555.  
  1556.   Count = ITEM_BASE_COUNT ;
  1557.  
  1558.   DosQCurDisk ( &Drive, &Drives ) ;
  1559.  
  1560.   for ( Drive=1; Drive<26; Drive++ )
  1561.   {
  1562.     if ( Drives & 1 )
  1563.     {
  1564.       USHORT Action ;
  1565.       USHORT Handle ;
  1566.       BYTE Path [3] ;
  1567.  
  1568.       Path[0] = (BYTE) ( Drive + 'A' - 1 ) ;
  1569.       Path[1] = ':' ;
  1570.       Path[2] = 0 ;
  1571.  
  1572.       if ( !DosOpen ( Path, &Handle, &Action, 0, 0, FILE_OPEN,
  1573.     OPEN_ACCESS_READONLY | OPEN_SHARE_DENYNONE |
  1574.     OPEN_FLAGS_DASD | OPEN_FLAGS_FAIL_ON_ERROR, 0 ) )
  1575.       {
  1576.     BIOSPARAMETERBLOCK BiosParms ;
  1577.     BYTE Command = 0 ;
  1578.  
  1579.     if ( !DosDevIOCtl ( &BiosParms, &Command, 0x0063, 0x0008, Handle ) )
  1580.     {
  1581.       if ( BiosParms.fsDeviceAttr & 1 )
  1582.       {
  1583.         char Name [40] ;
  1584.         char Label [40] ;
  1585.         char MenuOption [40] ;
  1586.  
  1587.         sprintf ( Name,      "ShowDrive%c:",      Drive+'A'-1 ) ;
  1588.         sprintf ( Label,      "Drive %c: free space", Drive+'A'-1 ) ;
  1589.         sprintf ( MenuOption, "Show %c: Free Space",  Drive+'A'-1 ) ;
  1590.  
  1591.         Items[Count].Name = malloc ( strlen(Name)+1 ) ;
  1592.         strcpy ( Items[Count].Name, Name ) ;
  1593.         Items[Count].Flag = TRUE ;
  1594.         Items[Count].Label = malloc ( strlen(Label)+1 ) ;
  1595.         strcpy ( Items[Count].Label, Label ) ;
  1596.         Items[Count].Value = 0L ;
  1597.         Items[Count].MenuOption = malloc ( strlen(MenuOption)+1 ) ;
  1598.         strcpy ( Items[Count].MenuOption, MenuOption ) ;
  1599.         Items[Count].MenuId = IDM_SHOW_DRIVE_FREE + Drive ;
  1600.         Items[Count].NewValue = ComputeDriveFree ;
  1601.         Items[Count].Parm = Drive ;
  1602.         Items[Count].Divisor = 1024 ;
  1603.         Items[Count].Suffix = 'K' ;
  1604.         Count ++ ;
  1605.       }
  1606.     }
  1607.     DosClose ( Handle ) ;
  1608.       }
  1609.     }
  1610.     Drives >>= 1 ;
  1611.   }
  1612.  
  1613.  /***********************************************************************
  1614.   * Save pointer to fixed configuration information.            *
  1615.   ***********************************************************************/
  1616.  
  1617.   Profile->Items = Items ;
  1618.   Profile->ItemCount = Count ;
  1619.  
  1620.  /***********************************************************************
  1621.   * Get the window's current size and position.                         *
  1622.   ***********************************************************************/
  1623.  
  1624.   memset ( &Profile->Position, 0, sizeof(Profile->Position) ) ;
  1625.   Profile->fPosition = FALSE ;
  1626.   if
  1627.   (
  1628.     PrfQueryProfileSize ( HINI_PROFILE, PROGRAM_NAME, "Position", &Size )
  1629.     AND
  1630.     ( Size == sizeof(Profile->Position) )
  1631.     AND
  1632.     PrfQueryProfileData ( HINI_PROFILE, PROGRAM_NAME, "Position", &Profile->Position, &Size )
  1633.   )
  1634.   {
  1635.     Profile->fPosition = TRUE ;
  1636.   }
  1637.  
  1638.  /***********************************************************************
  1639.   * Get the program options.                        *
  1640.   ***********************************************************************/
  1641.  
  1642.   Profile->HideControls = FALSE ;
  1643.   if
  1644.   (
  1645.     PrfQueryProfileSize ( HINI_PROFILE, PROGRAM_NAME, "HideControls", &Size )
  1646.     AND
  1647.     ( Size == sizeof(Profile->HideControls) )
  1648.     AND
  1649.     PrfQueryProfileData ( HINI_PROFILE, PROGRAM_NAME, "HideControls", &Profile->HideControls, &Size )
  1650.   )
  1651.   {
  1652.     ;
  1653.   }
  1654.  
  1655.  /***********************************************************************
  1656.   * Get the item options.                        *
  1657.   ***********************************************************************/
  1658.  
  1659.   for ( i=0; i<Profile->ItemCount; i++ )
  1660.   {
  1661.     ITEM *Item = & Profile->Items [i] ;
  1662.  
  1663.     Item->Flag = TRUE ;
  1664.     if
  1665.     (
  1666.       PrfQueryProfileSize ( HINI_PROFILE, PROGRAM_NAME, Item->Name, &Size )
  1667.       AND
  1668.       ( Size == sizeof(Item->Flag) )
  1669.       AND
  1670.       PrfQueryProfileData ( HINI_PROFILE, PROGRAM_NAME, Item->Name, &Item->Flag, &Size )
  1671.     )
  1672.     {
  1673.       ;
  1674.     }
  1675.   }
  1676.  
  1677.  /***********************************************************************
  1678.   * Get the presentation parameters.                    *
  1679.   ***********************************************************************/
  1680.  
  1681.   strcpy ( Profile->FontNameSize, "" ) ;
  1682.   Profile->fFontNameSize = FALSE ;
  1683.   if
  1684.   (
  1685.     PrfQueryProfileSize ( HINI_PROFILE, PROGRAM_NAME, "FontNameSize", &Size )
  1686.     AND
  1687.     ( Size == sizeof(Profile->FontNameSize) )
  1688.     AND
  1689.     PrfQueryProfileData ( HINI_PROFILE, PROGRAM_NAME, "FontNameSize", &Profile->FontNameSize, &Size )
  1690.   )
  1691.   {
  1692.     Profile->fFontNameSize = TRUE ;
  1693.   }
  1694.  
  1695.   Profile->BackColor = WinQuerySysColor ( HWND_DESKTOP, SYSCLR_WINDOW, 0L ) ;
  1696.   Profile->fBackColor = FALSE ;
  1697.   if
  1698.   (
  1699.     PrfQueryProfileSize ( HINI_PROFILE, PROGRAM_NAME, "BackgroundColor", &Size )
  1700.     AND
  1701.     ( Size == sizeof(Profile->BackColor) )
  1702.     AND
  1703.     PrfQueryProfileData ( HINI_PROFILE, PROGRAM_NAME, "BackgroundColor", &Profile->BackColor, &Size )
  1704.   )
  1705.   {
  1706.     Profile->fBackColor = TRUE ;
  1707.   }
  1708.  
  1709.   Profile->TextColor = WinQuerySysColor ( HWND_DESKTOP, SYSCLR_OUTPUTTEXT, 0L ) ;
  1710.   Profile->fTextColor = FALSE ;
  1711.   if
  1712.   (
  1713.     PrfQueryProfileSize ( HINI_PROFILE, PROGRAM_NAME, "ForegroundColor", &Size )
  1714.     AND
  1715.     ( Size == sizeof(Profile->TextColor) )
  1716.     AND
  1717.     PrfQueryProfileData ( HINI_PROFILE, PROGRAM_NAME, "ForegroundColor", &Profile->TextColor, &Size )
  1718.   )
  1719.   {
  1720.     Profile->fTextColor = TRUE ;
  1721.   }
  1722. }
  1723.  
  1724. /************************************************************************
  1725.  *                                                                      *
  1726.  *                 Put Profile Data                *
  1727.  *                                                                      *
  1728.  ************************************************************************/
  1729.  
  1730. static void PutProfile ( PROFILE *Profile )
  1731. {
  1732.  /***********************************************************************
  1733.   * Local Declarations                            *
  1734.   ***********************************************************************/
  1735.  
  1736.   int i ;
  1737.  
  1738.  /***********************************************************************
  1739.   * Save the window's current size and position.                        *
  1740.   ***********************************************************************/
  1741.  
  1742.   PrfWriteProfileData
  1743.   (
  1744.     HINI_USERPROFILE,
  1745.     PROGRAM_NAME,
  1746.     "Position",
  1747.     &Profile->Position,
  1748.     (ULONG)sizeof(Profile->Position)
  1749.   ) ;
  1750.  
  1751.  /***********************************************************************
  1752.   * Save the program options.                                           *
  1753.   ***********************************************************************/
  1754.  
  1755.   PrfWriteProfileData
  1756.   (
  1757.     HINI_USERPROFILE,
  1758.     PROGRAM_NAME,
  1759.     "HideControls",
  1760.     &Profile->HideControls,
  1761.     (ULONG)sizeof(Profile->HideControls)
  1762.   ) ;
  1763.  
  1764.  /***********************************************************************
  1765.   * Save the item options.                        *
  1766.   ***********************************************************************/
  1767.  
  1768.   for ( i=0; i<Profile->ItemCount; i++ )
  1769.   {
  1770.     ITEM *Item = & Profile->Items [i] ;
  1771.  
  1772.     PrfWriteProfileData
  1773.     (
  1774.       HINI_USERPROFILE,
  1775.       PROGRAM_NAME,
  1776.       Item->Name,
  1777.       &Item->Flag,
  1778.       (ULONG)sizeof(Item->Flag)
  1779.     ) ;
  1780.   }
  1781.  
  1782.  /***********************************************************************
  1783.   * Save the presentation parameters.                                   *
  1784.   ***********************************************************************/
  1785.  
  1786.   if ( Profile->fFontNameSize )
  1787.   {
  1788.     PrfWriteProfileData
  1789.     (
  1790.       HINI_USERPROFILE,
  1791.       PROGRAM_NAME,
  1792.       "FontNameSize",
  1793.       Profile->FontNameSize,
  1794.       (ULONG)sizeof(Profile->FontNameSize)
  1795.     ) ;
  1796.   }
  1797.  
  1798.   if ( Profile->fBackColor )
  1799.   {
  1800.     PrfWriteProfileData
  1801.     (
  1802.       HINI_USERPROFILE,
  1803.       PROGRAM_NAME,
  1804.       "BackgroundColor",
  1805.       &Profile->BackColor,
  1806.       (ULONG)sizeof(Profile->BackColor)
  1807.     ) ;
  1808.   }
  1809.  
  1810.   if ( Profile->fTextColor )
  1811.   {
  1812.     PrfWriteProfileData
  1813.     (
  1814.       HINI_USERPROFILE,
  1815.       PROGRAM_NAME,
  1816.       "ForegroundColor",
  1817.       &Profile->TextColor,
  1818.       (ULONG)sizeof(Profile->TextColor)
  1819.     ) ;
  1820.   }
  1821. }
  1822.  
  1823. /************************************************************************
  1824.  *                                                                      *
  1825.  *      Scan CONFIG.SYS for a keyword.  Return the value.               *
  1826.  *                                                                      *
  1827.  ************************************************************************/
  1828.  
  1829. static char *ScanSystemConfig ( char *Keyword )
  1830. {
  1831.  /***********************************************************************
  1832.   * Local Declarations                                                  *
  1833.   ***********************************************************************/
  1834.  
  1835.   static char Buffer [500] ;
  1836.   FILE *File ;
  1837.   SEL GlobalSelector ;
  1838.   SEL LocalSelector ;
  1839.   char Path [_MAX_PATH] ;
  1840.   GINFOSEG FAR *pGlobalInfoSeg ;
  1841.  
  1842.  /***********************************************************************
  1843.   * Get the boot drive number from the global information segment.    *
  1844.   ***********************************************************************/
  1845.  
  1846.   DosGetInfoSeg ( &GlobalSelector, &LocalSelector ) ;
  1847.  
  1848.   pGlobalInfoSeg = MAKEPGINFOSEG ( GlobalSelector ) ;
  1849.  
  1850.  /***********************************************************************
  1851.   * Build the CONFIG.SYS path.                        *
  1852.   ***********************************************************************/
  1853.  
  1854.   Path[0] = (char) ( pGlobalInfoSeg->bootdrive + 'A' - 1 ) ;
  1855.   Path[1] = 0 ;
  1856.   strcat ( Path, ":\\CONFIG.SYS" ) ;
  1857.  
  1858.  /***********************************************************************
  1859.   * Open CONFIG.SYS for reading.                    *
  1860.   ***********************************************************************/
  1861.  
  1862.   File = fopen ( Path, "rt" ) ;
  1863.   if ( NOT File )
  1864.   {
  1865.     return ( NULL ) ;
  1866.   }
  1867.  
  1868.  /***********************************************************************
  1869.   * While there're more lines in CONFIG.SYS, read a line and check it.  *
  1870.   ***********************************************************************/
  1871.  
  1872.   while ( fgets ( Buffer, sizeof(Buffer), File ) )
  1873.   {
  1874.  
  1875.    /*********************************************************************
  1876.     * Clean any trailing newline character from the input string.    *
  1877.     *********************************************************************/
  1878.  
  1879.     if ( Buffer[strlen(Buffer)-1] == '\n' )
  1880.     {
  1881.       Buffer[strlen(Buffer)-1] = 0 ;
  1882.     }
  1883.  
  1884.    /*********************************************************************
  1885.     * If keyword starts the line, we've found the line we want.  Close  *
  1886.     *    the file and return a pointer to the parameter text.        *
  1887.     *********************************************************************/
  1888.  
  1889.     if ( NOT strnicmp ( Buffer, Keyword, strlen(Keyword) )
  1890.       AND ( Buffer[strlen(Keyword)] == '=' ) )
  1891.     {
  1892.       fclose ( File ) ;
  1893.       return ( Buffer + strlen(Keyword) + 1 ) ;
  1894.     }
  1895.   }
  1896.  
  1897.  /***********************************************************************
  1898.   * Close the file.  We haven't found the line we wanted.               *
  1899.   ***********************************************************************/
  1900.  
  1901.   fclose ( File ) ;
  1902.  
  1903.   return ( NULL ) ;
  1904. }
  1905.  
  1906. /************************************************************************
  1907.  *                                                                      *
  1908.  *                       Resize Client Window                           *
  1909.  *                                                                      *
  1910.  ************************************************************************/
  1911.  
  1912. static void ResizeWindow ( HWND hwnd, PROFILE *Profile )
  1913. {
  1914.  /***********************************************************************
  1915.   * Local Declarations                                                  *
  1916.   ***********************************************************************/
  1917.  
  1918.   SHORT Count ;
  1919.   SHORT fHadToHide = FALSE ;
  1920.   SHORT fHadToRestore = FALSE ;
  1921.   LONG Height ;
  1922.   HPS hPS ;
  1923.   HWND hwndFrame ;
  1924.   short i ;
  1925.   RECTL Rectangle ;
  1926.   char Text [100] ;
  1927.   LONG Widest ;
  1928.  
  1929.  /***********************************************************************
  1930.   * If the window is visible and minimized, restore it invisibly.    *
  1931.   ***********************************************************************/
  1932.  
  1933.   hwndFrame = WinQueryWindow ( hwnd, QW_PARENT, FALSE ) ;
  1934.  
  1935.   if ( Profile->Position.fs & SWP_MINIMIZE )
  1936.   {
  1937.     if ( WinIsWindowVisible ( hwndFrame ) )
  1938.     {
  1939.       WinShowWindow ( hwndFrame, FALSE ) ;
  1940.       fHadToHide = TRUE ;
  1941.     }
  1942.     WinSetWindowPos ( hwndFrame, NULL, 0, 0, 0, 0, SWP_RESTORE ) ;
  1943.     fHadToRestore = TRUE ;
  1944.   }
  1945.  
  1946.  /***********************************************************************
  1947.   * Determine how many items are to be displayed.                       *
  1948.   ***********************************************************************/
  1949.  
  1950.   hPS = WinGetPS ( hwnd ) ;
  1951.  
  1952.   Count = 0 ;
  1953.   Widest = 0 ;
  1954.   Height = 0 ;
  1955.  
  1956.   for ( i=0; i<Profile->ItemCount; i++ )
  1957.   {
  1958.     ITEM *Item = & Profile->Items [i] ;
  1959.  
  1960.     if ( Item->Flag )
  1961.     {
  1962.       Count ++ ;
  1963.  
  1964.       sprintf ( Text, "%s 1,234,567K", Item->Label ) ;
  1965.  
  1966.       WinQueryWindowRect ( HWND_DESKTOP, &Rectangle ) ;
  1967.  
  1968.       WinDrawText ( hPS, strlen(Text), Text,
  1969.     &Rectangle, 0L, 0L, DT_LEFT | DT_BOTTOM | DT_QUERYEXTENT ) ;
  1970.  
  1971.       Widest = max ( Widest, (Rectangle.xRight-Rectangle.xLeft) ) ;
  1972.  
  1973.       Height += Rectangle.yTop - Rectangle.yBottom ;
  1974.     }
  1975.   }
  1976.  
  1977.   WinReleasePS ( hPS ) ;
  1978.  
  1979.  /***********************************************************************
  1980.   * Get the window's current size & position.                           *
  1981.   ***********************************************************************/
  1982.  
  1983.   WinQueryWindowRect ( hwndFrame, &Rectangle ) ;
  1984.  
  1985.   WinCalcFrameRect ( hwndFrame, &Rectangle, TRUE ) ;
  1986.  
  1987.  /***********************************************************************
  1988.   * Adjust the window's width & height.                                 *
  1989.   ***********************************************************************/
  1990.  
  1991.   Rectangle.xRight  = Rectangle.xLeft + Widest ;
  1992.  
  1993.   Rectangle.yTop    = Rectangle.yBottom + Height ;
  1994.  
  1995.  /***********************************************************************
  1996.   * Compute new frame size and apply it.                                *
  1997.   ***********************************************************************/
  1998.  
  1999.   WinCalcFrameRect ( hwndFrame, &Rectangle, FALSE ) ;
  2000.  
  2001.   WinSetWindowPos ( hwndFrame, NULL, 0, 0,
  2002.     (SHORT) (Rectangle.xRight-Rectangle.xLeft),
  2003.     (SHORT) (Rectangle.yTop-Rectangle.yBottom),
  2004.     SWP_SIZE ) ;
  2005.  
  2006.  /***********************************************************************
  2007.   * Return the window to its original state.                *
  2008.   ***********************************************************************/
  2009.  
  2010.   if ( fHadToRestore )
  2011.   {
  2012.     WinSetWindowPos ( hwndFrame, NULL,
  2013.       Profile->Position.x, Profile->Position.y,
  2014.       Profile->Position.cx, Profile->Position.cy,
  2015.       SWP_MOVE | SWP_SIZE | SWP_MINIMIZE ) ;
  2016.   }
  2017.  
  2018.   if ( fHadToHide )
  2019.   {
  2020.     WinShowWindow ( hwndFrame, TRUE ) ;
  2021.   }
  2022.  
  2023.  /***********************************************************************
  2024.   * Invalidate the window so that it gets repainted.                    *
  2025.   ***********************************************************************/
  2026.  
  2027.   WinInvalidateRect ( hwnd, NULL, TRUE ) ;
  2028. }
  2029.  
  2030. /************************************************************************
  2031.  *                                                                      *
  2032.  *            Hide Window Controls                *
  2033.  *                                                                      *
  2034.  ************************************************************************/
  2035.  
  2036. static void HideControls
  2037. (
  2038.   BOOL fHide,
  2039.   HWND hwndFrame,
  2040.   HWND hwndSysMenu,
  2041.   HWND hwndTitleBar,
  2042.   HWND hwndMinMax
  2043. )
  2044. {
  2045.  /***********************************************************************
  2046.   * Local Declarations                                                  *
  2047.   ***********************************************************************/
  2048.  
  2049.   SWP Position ;
  2050.   RECTL Rectangle ;
  2051.  
  2052.  /***********************************************************************
  2053.   * Determine client window and location.                *
  2054.   ***********************************************************************/
  2055.  
  2056.   WinQueryWindowPos ( hwndFrame, &Position ) ;
  2057.  
  2058.   Rectangle.xLeft   = Position.x ;
  2059.   Rectangle.xRight  = Position.x + Position.cx ;
  2060.   Rectangle.yBottom = Position.y ;
  2061.   Rectangle.yTop    = Position.y + Position.cy ;
  2062.  
  2063.   WinCalcFrameRect ( hwndFrame, &Rectangle, TRUE ) ;
  2064.  
  2065.  /***********************************************************************
  2066.   * Hide or reveal the controls windows by changing their parentage.    *
  2067.   ***********************************************************************/
  2068.  
  2069.   if ( fHide )
  2070.   {
  2071.     WinSetParent ( hwndSysMenu,  HWND_OBJECT, FALSE ) ;
  2072.     WinSetParent ( hwndTitleBar, HWND_OBJECT, FALSE ) ;
  2073.     WinSetParent ( hwndMinMax,     HWND_OBJECT, FALSE ) ;
  2074.   }
  2075.   else
  2076.   {
  2077.     WinSetParent ( hwndSysMenu,  hwndFrame, TRUE ) ;
  2078.     WinSetParent ( hwndTitleBar, hwndFrame, TRUE ) ;
  2079.     WinSetParent ( hwndMinMax,     hwndFrame, TRUE ) ;
  2080.   }
  2081.  
  2082.  /***********************************************************************
  2083.   * Tell the frame that things have changed.  Let it update the window. *
  2084.   ***********************************************************************/
  2085.  
  2086.   WinSendMsg ( hwndFrame, WM_UPDATEFRAME,
  2087.     MPFROMSHORT ( FCF_TITLEBAR | FCF_SYSMENU | FCF_MINBUTTON ), 0L ) ;
  2088.  
  2089.  /***********************************************************************
  2090.   * Reposition the frame around the client window, which is left be.    *
  2091.   ***********************************************************************/
  2092.  
  2093.   WinCalcFrameRect ( hwndFrame, &Rectangle, FALSE ) ;
  2094.  
  2095.   WinSetWindowPos ( hwndFrame, NULL,
  2096.     (SHORT) Rectangle.xLeft,  (SHORT) Rectangle.yBottom,
  2097.     (SHORT) (Rectangle.xRight-Rectangle.xLeft),
  2098.     (SHORT) (Rectangle.yTop-Rectangle.yBottom),
  2099.     SWP_SIZE | SWP_MOVE ) ;
  2100. }
  2101.  
  2102. /************************************************************************
  2103.  *                                                                      *
  2104.  *                       Display Debug Message                          *
  2105.  *                                                                      *
  2106.  ************************************************************************/
  2107.  
  2108. static void Debug ( HWND hwnd, char *Message, ... )
  2109. {
  2110.   va_list Marker ;
  2111.   char Text [500] ;
  2112.  
  2113.   va_start ( Marker, Message ) ;
  2114.   vsprintf ( Text, Message, Marker ) ;
  2115.   va_end ( Marker ) ;
  2116.  
  2117.   WinMessageBox ( HWND_DESKTOP, hwnd, Text, "Debug", 0, MB_ENTER ) ;
  2118. }
  2119.  
  2120. /************************************************************************
  2121.  *                                                                      *
  2122.  *    Calibrate the CPU Load Meter.                                     *
  2123.  *                                                                      *
  2124.  ************************************************************************/
  2125.  
  2126. static ULONG CalibrateLoad ( void )
  2127. {
  2128.   CALIBRATION_PARMS Parms ;
  2129.   PIDINFO PidInfo ;
  2130.   TID tid ;
  2131.  
  2132.   DosGetPID ( &PidInfo ) ;
  2133.  
  2134.   DosSetPrty ( PRTYS_THREAD, PRTYC_TIMECRITICAL, PRTYD_MAXIMUM, PidInfo.tid ) ;
  2135.  
  2136.   tid = _beginthread ( CalibrationThread, NULL, 4000, &Parms ) ;
  2137.  
  2138.   DosSleep ( 1000L ) ;
  2139.  
  2140.   DosSuspendThread ( tid ) ;
  2141.  
  2142.   DosSetPrty ( PRTYS_THREAD, PRTYC_REGULAR, 0, PidInfo.tid ) ;
  2143.  
  2144.   return ( Parms.Count ) ;
  2145. }
  2146.  
  2147. /************************************************************************
  2148.  *                                                                      *
  2149.  *    Thread to collect CPU loading statistics.                         *
  2150.  *                                                                      *
  2151.  ************************************************************************/
  2152.  
  2153. static void _cdecl _far TimingThread ( TIMING_PARMS *Parms )
  2154. {
  2155.   PIDINFO PidInfo ;
  2156.  
  2157.   DosGetPID ( &PidInfo ) ;
  2158.  
  2159.   DosSetPrty ( PRTYS_THREAD, PRTYC_TIMECRITICAL, PRTYD_MAXIMUM, PidInfo.tid ) ;
  2160.  
  2161.   *Parms->Count = 0 ;
  2162.  
  2163.   while ( TRUE )
  2164.   {
  2165.     DosSleep ( 1000L ) ;
  2166.  
  2167.     WinPostMsg ( Parms->hwndClient, WM_SEM1,
  2168.       MPFROMLONG ( *Parms->Count ), NULL ) ;
  2169.  
  2170.     *Parms->Count = 0 ;
  2171.   }
  2172. }
  2173.  
  2174. /************************************************************************
  2175.  *                                                                      *
  2176.  *    Thread to count unused CPU cycles.                                *
  2177.  *                                                                      *
  2178.  ************************************************************************/
  2179.  
  2180. static void _cdecl _far CountingThread ( COUNTING_PARMS *Parms )
  2181. {
  2182.   PIDINFO PidInfo ;
  2183.  
  2184.   DosGetPID ( &PidInfo ) ;
  2185.  
  2186.   DosSetPrty ( PRTYS_THREAD, PRTYC_IDLETIME, PRTYD_MINIMUM, PidInfo.tid ) ;
  2187.  
  2188.   while ( TRUE )
  2189.   {
  2190.     (*Parms->Count) ++ ;
  2191.   }
  2192. }
  2193.  
  2194. /************************************************************************
  2195.  *                                                                      *
  2196.  *    Thread to count CPU cycles per second.                            *
  2197.  *                                                                      *
  2198.  ************************************************************************/
  2199.  
  2200. static void _cdecl _far CalibrationThread ( CALIBRATION_PARMS *Parms )
  2201. {
  2202.   PIDINFO PidInfo ;
  2203.  
  2204.   DosGetPID ( &PidInfo ) ;
  2205.  
  2206.   DosSetPrty ( PRTYS_THREAD, PRTYC_TIMECRITICAL, PRTYD_MAXIMUM-1, PidInfo.tid ) ;
  2207.  
  2208.   Parms->Count = 0 ;
  2209.  
  2210.   while ( TRUE )
  2211.   {
  2212.     Parms->Count ++ ;
  2213.   }
  2214. }
  2215.  
  2216. /************************************************************************
  2217.  *                                                                      *
  2218.  *    Update Window                            *
  2219.  *                                                                      *
  2220.  ************************************************************************/
  2221.  
  2222. static void UpdateWindow ( HWND hwnd, DATA *Data, BOOL All )
  2223. {
  2224.  /***********************************************************************
  2225.   *                             Declarations                            *
  2226.   ***********************************************************************/
  2227.  
  2228.   int Count ;
  2229.   HPS hPS ;
  2230.   short i ;
  2231.   RECTL Rectangle ;
  2232.   char Text [40] ;
  2233.  
  2234.  /***********************************************************************
  2235.   * Determine how many items are to be displayed.                       *
  2236.   ***********************************************************************/
  2237.  
  2238.   Count = 0 ;
  2239.   for ( i=0; i<Data->Profile.ItemCount; i++ )
  2240.   {
  2241.     if ( Data->Profile.Items[i].Flag )
  2242.     {
  2243.       Count ++ ;
  2244.     }
  2245.   }
  2246.  
  2247.  /***********************************************************************
  2248.   * Get presentation space and make it use RGB colors.                  *
  2249.   ***********************************************************************/
  2250.  
  2251.   hPS = WinGetPS ( hwnd ) ;
  2252.   GpiCreateLogColorTable ( hPS, LCOL_RESET, LCOLF_RGB, 0L, 0L, NULL ) ;
  2253.  
  2254.  /***********************************************************************
  2255.   * Get the window's size and determine the initial position.           *
  2256.   ***********************************************************************/
  2257.  
  2258.   WinQueryWindowRect ( hwnd, &Rectangle ) ;
  2259.  
  2260.   Rectangle.xLeft += Data->FontMetrics.lAveCharWidth / 2 ;
  2261.   Rectangle.xRight -= Data->FontMetrics.lAveCharWidth / 2 ;
  2262.  
  2263.   Rectangle.yBottom = Data->FontMetrics.lMaxBaselineExt * ( Count - 1 ) ;
  2264.   Rectangle.yTop = Rectangle.yBottom + Data->FontMetrics.lMaxBaselineExt - 1 ;
  2265.  
  2266.  /***********************************************************************
  2267.   * Review all items.  Display those changed, or all.            *
  2268.   ***********************************************************************/
  2269.  
  2270.   for ( i=0; i<Data->Profile.ItemCount; i++ )
  2271.   {
  2272.     ITEM *Item = & Data->Profile.Items [i] ;
  2273.     ULONG NewValue ;
  2274.  
  2275.     if ( Item->Flag )
  2276.     {
  2277.       NewValue = Item->NewValue ( Data, Item->Parm ) ;
  2278.  
  2279.       if ( All OR ( NewValue != Item->Value ) )
  2280.       {
  2281.     memset ( Text, 0, sizeof(Text) ) ;
  2282.  
  2283.     if ( Item->Divisor )
  2284.     {
  2285.       if ( NewValue < Item->Divisor * 1000 )
  2286.         sprintf ( Text, "%lu", NewValue ) ;
  2287.       else
  2288.         sprintf ( Text, "%lu", (NewValue+Item->Divisor/2)/Item->Divisor ) ;
  2289.     }
  2290.     else
  2291.     {
  2292.       sprintf ( Text, "%lu", NewValue ) ;
  2293.     }
  2294.  
  2295.     {
  2296.       PCHAR p1, p2 ;
  2297.       CHAR Work[100] ;
  2298.  
  2299.       p1 = Text ;
  2300.       p2 = Work ;
  2301.       while ( *p1 )
  2302.       {
  2303.         *p2 = *p1 ;
  2304.         p1 ++ ;
  2305.         p2 ++ ;
  2306.         if ( *p1 )
  2307.         {
  2308.           if ( strlen(p1) % 3 == 0 )
  2309.           {
  2310.         *p2 = ',' ;
  2311.         p2 ++ ;
  2312.           }
  2313.         }
  2314.       }
  2315.       *p2 = 0 ;
  2316.       strcpy ( Text, Work ) ;
  2317.     }
  2318.  
  2319.     if ( Item->Divisor )
  2320.     {
  2321.       if ( NewValue < Item->Divisor * 1000 )
  2322.         Text[strlen(Text)] = ' ' ;
  2323.       else
  2324.         Text[strlen(Text)] = Item->Suffix ;
  2325.     }
  2326.     else
  2327.     {
  2328.       Text[strlen(Text)] = Item->Suffix ;
  2329.     }
  2330.  
  2331.     WinDrawText ( hPS, strlen(Text), Text, &Rectangle,
  2332.       Data->Profile.TextColor, Data->Profile.BackColor,
  2333.       DT_RIGHT | DT_BOTTOM | DT_ERASERECT ) ;
  2334.  
  2335.     strcpy ( Text, Item->Label ) ;
  2336.  
  2337.     WinDrawText ( hPS, strlen(Text), Text, &Rectangle,
  2338.       Data->Profile.TextColor, Data->Profile.BackColor,
  2339.       DT_LEFT | DT_BOTTOM ) ;
  2340.  
  2341.     Item->Value = NewValue ;
  2342.       }
  2343.       Rectangle.yBottom -= Data->FontMetrics.lMaxBaselineExt ;
  2344.       Rectangle.yTop    -= Data->FontMetrics.lMaxBaselineExt ;
  2345.     }
  2346.   }
  2347.  
  2348.  /***********************************************************************
  2349.   * Release the presentation space and return.                *
  2350.   ***********************************************************************/
  2351.  
  2352.   WinReleasePS ( hPS ) ;
  2353. }
  2354.  
  2355. /************************************************************************
  2356.  *                                                                      *
  2357.  *    Compute Available Memory                        *
  2358.  *                                                                      *
  2359.  ************************************************************************/
  2360.  
  2361. static ULONG ComputeFreeMemory ( DATA *Data, USHORT Dummy )
  2362. {
  2363.   ULONG MemFree ;
  2364.  
  2365.   DosMemAvail ( &MemFree ) ;
  2366.  
  2367.   return ( MemFree ) ;
  2368. }
  2369.  
  2370. /************************************************************************
  2371.  *                                                                      *
  2372.  *    Compute Swap-File Size                        *
  2373.  *                                                                      *
  2374.  ************************************************************************/
  2375.  
  2376. static ULONG ComputeSwapSize ( DATA *Data, USHORT Dummy )
  2377. {
  2378.  /***********************************************************************
  2379.   *                             Declarations                            *
  2380.   ***********************************************************************/
  2381.  
  2382.   char Path [_MAX_PATH+1] ;
  2383.   struct stat Status ;
  2384.   ULONG SwapSize ;
  2385.  
  2386.  /***********************************************************************
  2387.   * Find the swap file and find its size.                               *
  2388.   ***********************************************************************/
  2389.  
  2390.   strcpy ( Path, Data->SwapPath ) ;
  2391.  
  2392.   if ( Path[strlen(Path)-1] != '\\' )
  2393.   {
  2394.     strcat ( Path, "\\" ) ;
  2395.   }
  2396.  
  2397.   strcat ( Path, "SWAPPER.DAT" ) ;
  2398.  
  2399.   SwapSize = 0 ;
  2400.   if ( stat ( Path, &Status ) == 0 )
  2401.   {
  2402.     SwapSize = Status.st_size ;
  2403.   }
  2404.  
  2405.   return ( SwapSize ) ;
  2406. }
  2407.  
  2408. /************************************************************************
  2409.  *                                                                      *
  2410.  *    Compute Available Swap Space                    *
  2411.  *                                                                      *
  2412.  ************************************************************************/
  2413.  
  2414. static ULONG ComputeSwapFree ( DATA *Data, USHORT Dummy )
  2415. {
  2416.  /***********************************************************************
  2417.   *                             Declarations                            *
  2418.   ***********************************************************************/
  2419.  
  2420.   FSALLOCATE Allocation ;
  2421.   char Path [_MAX_PATH+1] ;
  2422.   ULONG SwapFree ;
  2423.  
  2424.  /***********************************************************************
  2425.   * Find the swap file and find its size.                               *
  2426.   ***********************************************************************/
  2427.  
  2428.   strcpy ( Path, Data->SwapPath ) ;
  2429.   strcat ( Path, "\\SWAPPER.DAT" ) ;
  2430.  
  2431.  /***********************************************************************
  2432.   * Compute swap device free space.                                     *
  2433.   ***********************************************************************/
  2434.  
  2435.   SwapFree = 0 ;
  2436.   if ( Path[0] )
  2437.   {
  2438.     DosQFSInfo ( Path[0]-'A'+1, FSIL_ALLOC,
  2439.       (PBYTE)&Allocation, sizeof(Allocation) ) ;
  2440.  
  2441.     SwapFree = Allocation.cUnitAvail*Allocation.cSectorUnit*Allocation.cbSector ;
  2442.   }
  2443.  
  2444.  /***********************************************************************
  2445.   * Return swap device's free space, less the minimum free space.       *
  2446.   ***********************************************************************/
  2447.  
  2448.   if ( SwapFree < (ULONG)Data->MinFree*1024L )
  2449.     return ( 0L ) ;
  2450.   else
  2451.     return ( SwapFree - (ULONG)Data->MinFree * 1024L ) ;
  2452. }
  2453.  
  2454. /************************************************************************
  2455.  *                                                                      *
  2456.  *    Compute Spool-file Size                        *
  2457.  *                                                                      *
  2458.  ************************************************************************/
  2459.  
  2460. static ULONG ComputeSpoolSize ( DATA *Data, USHORT Dummy )
  2461. {
  2462.   USHORT Count ;
  2463.   FILEFINDBUF *Found ;
  2464.   HDIR hDir = HDIR_CREATE ;
  2465.   BYTE *Path ;
  2466.   USHORT PathSize ;
  2467.   ULONG TotalSize = 0 ;
  2468.  
  2469.   DosQSysInfo ( 0, (BYTE*)&PathSize, sizeof(PathSize) ) ;
  2470.  
  2471.   Path = malloc ( PathSize ) ;
  2472.   if ( Path == NULL )
  2473.   {
  2474.     return ( 0 ) ;
  2475.   }
  2476.  
  2477.   Found = malloc ( PathSize + sizeof(FILEFINDBUF) ) ;
  2478.   if ( Found == NULL )
  2479.   {
  2480.     free ( Path ) ;
  2481.     return ( 0 ) ;
  2482.   }
  2483.  
  2484.   strcpy ( Path, Data->SpoolPath ) ;
  2485.   strcat ( Path, "\\*.*" ) ;
  2486.  
  2487.   Count = 1 ;
  2488.   if ( !DosFindFirst ( Path, &hDir,
  2489.     FILE_NORMAL | FILE_READONLY | FILE_DIRECTORY | FILE_ARCHIVED,
  2490.     Found, PathSize+sizeof(FILEFINDBUF), &Count, 0L ) )
  2491.   {
  2492.     do
  2493.     {
  2494.       if ( !strcmp ( Found->achName, "." )
  2495.     OR !strcmp ( Found->achName, ".." ) )
  2496.       {
  2497.     continue ;
  2498.       }
  2499.  
  2500.       if ( Found->attrFile & FILE_DIRECTORY )
  2501.       {
  2502.     HDIR hDir = HDIR_CREATE ;
  2503.  
  2504.     strcpy ( Path, Data->SpoolPath ) ;
  2505.     strcat ( Path, "\\" ) ;
  2506.     strcat ( Path, Found->achName ) ;
  2507.     strcat ( Path, "\\*.*" ) ;
  2508.  
  2509.     Count = 1 ;
  2510.     if ( !DosFindFirst ( Path, &hDir,
  2511.       FILE_NORMAL | FILE_READONLY | FILE_ARCHIVED,
  2512.       Found, PathSize+sizeof(FILEFINDBUF), &Count, 0L ) )
  2513.     {
  2514.       do
  2515.       {
  2516.         TotalSize += Found->cbFileAlloc ;
  2517.       }
  2518.       while ( !DosFindNext ( hDir, Found, PathSize+sizeof(FILEFINDBUF), &Count ) ) ;
  2519.       DosFindClose ( hDir ) ;
  2520.       Count = 1 ;
  2521.     }
  2522.       }
  2523.       else
  2524.       {
  2525.     TotalSize += Found->cbFileAlloc ;
  2526.       }
  2527.     }
  2528.     while ( !DosFindNext ( hDir, Found, PathSize+sizeof(FILEFINDBUF), &Count ) ) ;
  2529.     DosFindClose ( hDir ) ;
  2530.   }
  2531.  
  2532.   free ( Path ) ;
  2533.   free ( Found ) ;
  2534.  
  2535.   return ( TotalSize ) ;
  2536. }
  2537.  
  2538. /************************************************************************
  2539.  *                                                                      *
  2540.  *    Compute CPU Load                            *
  2541.  *                                                                      *
  2542.  ************************************************************************/
  2543.  
  2544. static ULONG ComputeCpuLoad ( DATA *Data, USHORT Dummy )
  2545. {
  2546.   return ( Data->NewLoad ) ;
  2547. }
  2548.  
  2549. /************************************************************************
  2550.  *                                                                      *
  2551.  *    Compute Drive Free Space                        *
  2552.  *                                                                      *
  2553.  ************************************************************************/
  2554.  
  2555. static ULONG ComputeDriveFree ( DATA *Data, USHORT Drive )
  2556. {
  2557.   FSALLOCATE Allocation ;
  2558.  
  2559.   DosQFSInfo ( Drive, FSIL_ALLOC,
  2560.     (PBYTE)&Allocation, sizeof(Allocation) ) ;
  2561.  
  2562.   return ( Allocation.cUnitAvail*Allocation.cSectorUnit*Allocation.cbSector ) ;
  2563. }
  2564.